#pragma once

#include "obj_fun.h"

namespace xtd {

/// Suppose you have a container, which allows access to the stored elements only by index.
/// If you wish also iterator access then this is the solution.

/// F - access functor which takes single argument - element index (i.e. xtd::obj_fun1_t)
template <typename F> 
class index_iterator_t {
public:
	typedef F accessor_type;
	typedef typename F::argument_type index_type;
	typedef typename F::result_type value_type;

	index_iterator_t() { }
	index_iterator_t(accessor_type accessor, index_type index)
		: accessor_(accessor), index_(index) { }
	index_iterator_t(const index_iterator_t & rhs)
		: accessor_(rhs.accessor_), index_(rhs.index_) { }
	bool operator == (const index_iterator_t & rhs) const
		{ return index_ == rhs.index_; }
	bool operator != (const index_iterator_t & rhs) const
		{ return index_ != rhs.index_; }
	index_iterator_t & operator ++() {
		++index_;
		return * this;
	}
	index_iterator_t & operator --() {
		--index_;
		return * this;
	}
	value_type operator * ()
		{	return accessor_(index_);	}
private:
	accessor_type accessor_;
	index_type index_;
};

template <class T, class R, class A>
inline index_iterator_t< obj_fun1_t<T,R,A> > index_iterator(T & obj, R (T::*fun)(A), A index)
	{ return index_iterator_t< obj_fun1_t<T,R,A> >(obj_fun(obj, fun), index); }

template <class T, class R, class A>
inline index_iterator_t< obj_fun1c_t<T,R,A> > index_iterator(T & obj, R (T::*fun)(A) const, A index)
	{ return index_iterator_t< obj_fun1c_t<T,R,A> >(obj_fun(obj, fun), index); }

} // xtd
